package org.assistant.common.web.servlet.mvc;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class Controller extends HttpServlet {
	private static final long serialVersionUID = -2182449758277803952L;
	protected final static Log log = LogFactory.getLog(Controller.class);
	protected final static boolean isDebugEnabled = log.isDebugEnabled();

	private static final String PREFIX = "/jsp";// 页面的前缀

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String methodName = getMethodName(request);// 获取当前请求的方法名
		if (isDebugEnabled) {
			log.debug("methodName = " + methodName);
		}

		// 请求分发
		Object result = requestDispatcher(request, response, methodName);
		if (result == null) {
			log.error("Controller中函数的返回值不能为空!");
			throw new RuntimeException("Controller中函数的返回值不能为空!");
		} else if (result instanceof Page) {// 处理返回页面的请求
			String page = PREFIX + ((Page) result).getPage();
			request.getRequestDispatcher(page).forward(request, response);
			return;
		} else if (result instanceof ResultData<?>) {// 处理返回Data的请求
			ResultData<?> resultData = null;
			if (result == null) {
				resultData = new ResultData<Object>();
				StringBuffer msg = new StringBuffer("Controller中函数[ ");
				msg.append(methodName);
				msg.append(" ]的没有返回任何数据!");
				log.error(msg.toString());
				resultData.setException(msg.toString());
			} else {
				resultData = (ResultData<?>) result;
			}

			response.setContentType("text/javascript;charset=UTF-8");
			response.setHeader("Cache-Control", "no-cache");
			PrintWriter out = null;
			try {
				out = response.getWriter();
				if (resultData.getType() == DataType.original_json) {
					out.println(resultData.getData());
				} else if (resultData.getType() == DataType.original_xml) {
					response.setContentType("text/xml;charset=UTF-8");
					out.println(resultData.getData());
				} else {
					out.println(resultData.getJSONString());
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				out.close();
			}
		} else {
			throw new RuntimeException(
				"Controller中函数的返回类型只能是Page或者是ResultData!");
		}
	}

	/**
	 * 请求分发器，子类需要实现该分发器
	 * 
	 * @param request
	 * @param response
	 * @param methodName
	 *            请求的方法名，在子类中应该根据该方法名调用相应的函数
	 * @return
	 */
	protected abstract Object requestDispatcher(HttpServletRequest request,
			HttpServletResponse response, String methodName);

	/**
	 * 获取当前请求的方法名
	 * 
	 * @param request
	 * @return
	 */
	public String getMethodName(HttpServletRequest request) {
		return MethodNameParserFactory.getInstance().getMethodName(request);
	}
}
